<?php

require_once("functions.php");

class DarwinCoreArchiveReader {
	public $fp_core;
	public $csvFields = array();
	private $archive_directory;
	private $idFlag = false;

	public $dwcFields = array(
			"scientificnameauthorship"
		,	"scientificname"
		,	"genus"
		,	"family"
		,	"class"
		,	"order"
		,	"taxonrank"
	);

	function __construct($uri) {
		$this->load_archive($uri);
		$this->load_core_metadata();
		$this->fp_core = fopen($this->core->file_uri, 'r');
	}

	function __destruct() {
		$this->cleanup();
	}

	function load_archive($uri, $local = true) {
		$fileType = '';

		// currently only recognizing tarred and gzipped files
		if(!preg_match("/^(.*)\.(tgz|tar\.gz|tar\.gzip|zip)$/", $uri, $arr)) throw new Exception("DarwinCore Archive must be tar/gzip/zip");
		if (!$local) {
			$file_contents = get_remote_file($uri);
			if(!$file_contents) throw new Exception("Cannot access DarwinCore Archive at $uri");
		}
		$directory_name = $arr[1];

		$fileType = (preg_match("/^(.*)\.(zip)$/", $uri, $arr)) ? 'zip' : $fileType;
		
		# make temp dir
		$this->archive_directory = create_temp_dir();
		if($fileType == 'zip') {
			$temp_file_path = $this->archive_directory ."/dwca.zip";
			if ($local) {
				$zip = new ZipArchive;
				$res = $zip->open($uri);
				if ($res === TRUE) {
					$zip->extractTo($this->archive_directory);
					$zip->close();
				}
			}

		} else {
			# copy contents to temp gzip file
			$temp_file_path = $this->archive_directory ."/dwca.tar.gz";

			$TMP = fopen($temp_file_path, "w+");
			fwrite($TMP, $file_contents);
			fclose($TMP);

			# extract contents of temp gzip file to temp dir
			$output = shell_exec("tar -xzf $temp_file_path -C $this->archive_directory");
		}
	}

	function cleanup() {
		// remove tmp dir
		if($this->archive_directory) shell_exec("rm -fr $this->archive_directory");
	}

	function load_core_metadata() {

		$metaFiles = davai($this->archive_directory, "meta.xml");
		if ($metaFiles) {
		foreach($metaFiles as $f) {
			if ($f["file"] == "meta.xml") {
#				$metadata_xml = get_hashed_response($this->archive_directory . "/meta.xml");
				$metadata_xml = get_hashed_response($f["dir"] . "/meta.xml");
				$this->archive_directory = $f["dir"];
				break;
			}
		}
		}
		$this->core = $this->load_core_or_extension($metadata_xml->core);
	
		$this->extensions = array();
		foreach($metadata_xml->extension as $extension_xml){
			$extension_object = $this->load_core_or_extension($extension_xml);
			$this->extensions[strtolower($extension_object->row_type)] = $extension_object;
		}
	}

	function load_core_or_extension($metadata_xml) {
		$extension = new stdClass;
	
		// attributes
		$extension->row_type = import_decode(@$metadata_xml['rowType']);
		$extension->fields_terminated_by = import_decode(@$metadata_xml['fieldsTerminatedBy']);
		$extension->lines_terminated_by = import_decode(@$metadata_xml['linesTerminatedBy']);
		$extension->fields_enclosed_by = import_decode(@$metadata_xml['fieldsEnclosedBy']);
		$extension->compression = import_decode(@$metadata_xml['compression']);
		$extension->encoding = import_decode(@$metadata_xml['encoding']);
		$extension->ignore_header_lines = import_decode(@$metadata_xml['ignoreHeaderLines']);
		$extension->date_format = import_decode(@$metadata_xml['date_format']);
	
		// defaults
		if(!$extension->fields_terminated_by) $extension->core_field_terminator = "\t";
		if(!$extension->lines_terminated_by) $extension->core_line_terminator = "\n";
		if(!$extension->encoding) $extension->core_encoding = "ISO-8859-1";
		if(!$extension->ignore_header_lines) $extension->ignore_header_lines = 0;
	
		// SimpleXML turns \n into \\n which will confuse other things
		$extension->fields_terminated_by = self::convert_escaped_chars($extension->fields_terminated_by);
		$extension->lines_terminated_by = self::convert_escaped_chars($extension->lines_terminated_by);
		$extension->fields_enclosed_by = self::convert_escaped_chars($extension->fields_enclosed_by);
	
		// file location
		$extension->file_uri = (string) $metadata_xml->files->location;

#echo '<br> Metafile Location : ' . $extension->file_uri;

		// the URI is relative so add the path to the temp directory
		if(strpos($extension->file_uri, "/") === false){
			$extension->file_uri = $this->archive_directory ."/". $extension->file_uri;
		}

#echo '<br> Metafile : ' . $extension->file_uri;

		// fields
		$extension->fields = array();
		$extension->constants = array();
	
		// grabbing the ID if it exists
		if($id = $metadata_xml->id){
			$index = (int) @$id['index'];
			$term = (string) @$id['term'];
			$type = (string) @$id['type'];
			if(!$term) $term = "http://rs.tdwg.org/dwc/terms/taxonID";
			$extension->fields[$index] = array('term' => $term,
			$extension->id = $extension->fields[$index]);
		}
	
		// grabbing the coreID if it exists
		if($id = $metadata_xml->coreid){
			$index = (int) @$id['index'];
			$term = (string) @$id['term'];
			$type = (string) @$id['type'];
			if(!$term) $term = "http://rs.tdwg.org/dwc/terms/taxonID";
			$extension->fields[$index] = array('term'      => $term,
			$extension->core_id = $extension->fields[$index]);
		}
	
		// now all other fields
		foreach($metadata_xml->field as $field){
			$index = (int) @$field['index'];
			$field_meta = array(
					'term' => (string) @$field['term']
				,	'type' => (string) @$field['type']
				,	'default' => (string) @$field['default']
			);
			if(isset($field['index'])) $extension->fields[$index] = $field_meta;
			else $extension->constants[] = $field_meta;
		}
		$extension->column_count = count($extension->fields);
	
		return $extension;
	}

	public function generateCoreSQL($sqlFile) {
		$fpsql = fopen($sqlFile,'a');
		fwrite($fpsql,$dwcsql);
	
	
		$dwcstr = '';
		$extrastr = '';
		$first = true;
		$line_num = 0;
		$i = 0;
	
		if(strtolower(pathinfo($this->core->file_uri,PATHINFO_EXTENSION)) == 'csv') {
	
			$fp = fopen($this->core->file_uri,'r');
			if (($fp = fopen($this->core->file_uri, 'r')) !== FALSE) {
				while (($fields = fgetcsv($fp, '', $this->core->fields_terminated_by)) !== FALSE) {
					$line_num++;
					if($this->core->ignore_header_lines && $line_num == 1) {
						array_walk($fields,'ustrtolower');
						$this->csvFields = $fields;
						if(!in_array('id',$this->csvFields)) {
							$this->idFlag = true;
						}
						continue;
					}

					$data = $this->getDataArrays($fields);
					$data = $this->transformRow($data);

					if($this->idFlag) {
						$i++;
						$data['dwc']['id'] =  $i;
					}

					$values = array();
					$writeFlag = true;
					if(!$first) {$dwcstr .= ",\r\n";$extrastr .= ",\r\n";}
					$first = false;

					foreach($this->dwcFields as $field) {
						$field = ($field == 'Order_') ? 'Order' : $field;
						$field = @strtolower($field);
		//      $values[] = "'" . $data['dwc'][$field] . "'";
						$values[] = $data['dwc'][$field];
					}
					//$dwcstr .= ' ( ' . implode(',',$values) . ' ) ';
					$dwcstr .=  implode(',',$values);
					unset($values);

					if($line_num > 40) break;

					if($line_num > 50) {
						fwrite($fpsql,$dwcstr);
						$dwcstr = '';
						fwrite($fpextra,$extrastr);
						$extrastr = '';

						$line_num = 0;
						$writeFlag = false;
					}
				} # while
				if($writeFlag) {fwrite($fpsql,$dwcstr);}
				fclose($fpsql);
			}
			fclose($fp);
			return true;
		} # type check
		return false;
	}

	private static function convert_escaped_chars($str) {
		// strcmp does a case insensitive string comparison
		if(strcasecmp($str, "\\n") == 0) return "\n";
		if(strcasecmp($str, "\\r") == 0) return "\r";
		if(strcasecmp($str, "\\t") == 0) return "\t";
		if(strcasecmp($str, "/n") == 0) return null;
		return $str;
	}

	public function getDataArrays($fields) {
		$fields = $this->generate_taxon($fields);
		foreach($this->dwcFields as $fld) {
			if(isset($fields[$fld])) {
				$dwcArray[$fld] = $fields[$fld];
			}
		}
		return($dwcArray);
	}

	public function generate_taxon($fields) {
		$row = array();
	
		for($i=0;$i<count($this->core->fields);$i++) {
			$meta = $this->core->fields[$i];
			$row[@strtolower(@basename($meta['term']))] = ($fields[$i] == '') ? $meta['default'] : $fields[$i];
		}
		return $row;
	}

	public function transformRow($rows) {
		$row = $rows['dwc'];
		$row['collectioncode'] = $row['institutioncode'];
		$row['institutioncode'] = 'UT';
		$row['globaluniqueidentifier'] = $row['institutioncode'] . ':' . $row['collectioncode'] . ':' . $row['catalognumber'];
		$rows['dwc'] = $row;
		$rows['extra']['globaluniqueidentifier'] = $row['globaluniqueidentifier'];
		return $rows;
	}

	public function getRow(){
		static $line_num = 0;
		$fields = fgetcsv($this->fp_core, '', $this->core->fields_terminated_by);
		if (!$fields) return(false);

		if($this->core->ignore_header_lines == 0 && $line_num == 0) {
			array_walk($fields,'ustrtolower');
			$this->csvFields = $fields;
			if(!in_array('id', $this->csvFields)) {
				$this->idFlag = true;
			}
			$fields = fgetcsv($this->fp_core, '', $this->core->fields_terminated_by);
		}
		$line_num++;
		$data = $this->getDataArrays($fields);
		return($data);
	}

	public function openCore() {
		$this->fp_core = fopen($this->core->file_uri,'r');
		
		if (($this->fp_core = fopen($this->core->file_uri, 'r')) !== FALSE) {
			return(true);
		} else {
			return(false);
		}
	}

}

function ustrtolower(&$field) {
	$field = strtolower($field);
}

?>